package control

import (
	"errors"
	"manager/db"
	"manager/model"

	"hiscene.com/openplatform/common/logger"
)

var (
	lamps     map[uint64]*model.Lamp
	boards    map[uint64]*model.Board
	macboards map[string]*model.Board
	addlamp   chan *model.Lamp
	addboard  chan *model.Board
	stopsrv   chan bool
)

// 错误定义
var (
	ErrDB = errors.New("open db error")
)

////////////////////////////////////////////////////////////////////////////////

func init() {
	addlamp = make(chan *model.Lamp, 10)
	addboard = make(chan *model.Board, 10)
	stopsrv = make(chan bool)
}

////////////////////////////////////////////////////////////////////////////////

// Start 启动,加载数据
func Start() error {
	cdb := db.GetDB()
	if cdb == nil {
		return ErrDB
	}

	lampArr := make([]*model.Lamp, 0)
	if sdb := cdb.Find(&lampArr); sdb.Error != nil {
		logger.Log4g.Error("load lamps error: %v", sdb.Error)
		return sdb.Error
	}

	boardArr := make([]*model.Board, 0)
	if sdb := cdb.Find(&boardArr); sdb.Error != nil {
		logger.Log4g.Error("load boards error: %v", sdb.Error)
		return sdb.Error
	}

	lamps = make(map[uint64]*model.Lamp)
	for _, lamp := range lampArr {
		if lamp != nil {
			lamps[lamp.ID] = lamp
		}
	}

	boards = make(map[uint64]*model.Board)
	macboards = make(map[string]*model.Board)
	for _, board := range boardArr {
		if board != nil {
			boards[board.ID] = board
			macboards[board.Mac] = board
		}
	}

	go func() {
		for {
			select {
			case <-stopsrv:
				{
					goto EXIT
				}
			case lamp, ok := <-addlamp:
				{
					if ok == false || lamp == nil {
						continue
					}
					lamps[lamp.ID] = lamp
				}
			case board, ok := <-addboard:
				{
					if ok == false || board == nil {
						continue
					}
					boards[board.ID] = board
					macboards[board.Mac] = board
				}
			}
		}
	EXIT:
		stopsrv <- true
	}()
	return nil
}

// Stop 关闭
func Stop() {
	stopsrv <- true
	<-stopsrv
}

////////////////////////////////////////////////////////////////////////////////

// GetBoard 获取开发板
func GetBoard(mac string) *model.Board {
	board, ok := macboards[mac]
	if ok == false || board == nil {
		cdb := db.GetDB()
		if cdb != nil {
			board = &model.Board{}
			if sdb := cdb.Find(board, "mac = ? and disable = false", mac); sdb.Error != nil {
				logger.Log4g.Error("get board error: %v", sdb.Error)
				return nil
			}
			if board.ID <= 0 {
				return nil
			}
			AddBoard(board)
		}
	}
	return board
}

// GetBoardByID 获取开发板
func GetBoardByID(id uint64) *model.Board {
	board, ok := boards[id]
	if ok == false || board == nil {
		cdb := db.GetDB()
		if cdb != nil {
			board = &model.Board{}
			if sdb := cdb.Find(board, "id = ?", id); sdb.Error != nil {
				logger.Log4g.Error("get board error: %v", sdb.Error)
				return nil
			}
			if board.ID <= 0 {
				return nil
			}
			AddBoard(board)
		}
	}
	return board
}

// AddBoard 增加board
func AddBoard(board *model.Board) {
	addboard <- board
}

// SaveBoard 保存
func SaveBoard(board *model.Board) {
	cdb := db.GetDB()
	if cdb != nil {
		if board.ID <= 0 {
			if sdb := cdb.Create(board); sdb.Error != nil {
				logger.Log4g.Error("save board create error: %v", sdb.Error)
			} else {
				AddBoard(board)
			}
		} else {
			if sdb := cdb.Model(board).Update(board); sdb.Error != nil {
				logger.Log4g.Error("save board update error: %v", sdb.Error)
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////

// GetLamp 获取灯
func GetLamp(board uint64, key string) *model.Lamp {
	for _, lamp := range lamps {
		if lamp != nil && lamp.BoardID == board && lamp.Key == key {
			return lamp
		}
	}
	cdb := db.GetDB()
	if cdb != nil {
		lamp := &model.Lamp{}
		if sdb := cdb.Find(lamp, "board_id = ? and key = ?", board, key); sdb.Error != nil {
			logger.Log4g.Error("get lamp error: %v", sdb.Error)
			return nil
		}
		if lamp.ID <= 0 {
			return nil
		}
		AddLamp(lamp)
		return lamp
	}
	return nil
}

// GetLampByID 获取灯
func GetLampByID(id uint64) *model.Lamp {
	lamp, ok := lamps[id]
	if ok == false || lamp == nil {
		cdb := db.GetDB()
		if cdb != nil {
			lamp = &model.Lamp{}
			if sdb := cdb.Find(lamp, "id = ?", id); sdb.Error != nil {
				logger.Log4g.Error("get lamp by id error: %v", sdb.Error)
				return nil
			}
			if lamp.ID <= 0 {
				return nil
			}
			AddLamp(lamp)
		}
	}
	return lamp
}

// AddLamp 增加lamp
func AddLamp(lamp *model.Lamp) {
	addlamp <- lamp
}

// SaveLamp 保存
func SaveLamp(lamp *model.Lamp) {
	cdb := db.GetDB()
	if cdb != nil {
		if lamp.ID <= 0 {
			if sdb := cdb.Create(lamp); sdb.Error != nil {
				logger.Log4g.Error("save lamp create error: %v", sdb.Error)
			} else {
				AddLamp(lamp)
			}
		} else {
			if sdb := cdb.Model(lamp).Update(lamp); sdb.Error != nil {
				logger.Log4g.Error("save lamp update error: %v", sdb.Error)
			}
		}
	}
}
